﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Globalization
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design
Imports System.Workflow.ComponentModel.Serialization

Namespace System.Workflow.ComponentModel
    <TypeDescriptionProvider(GetType(CompositeActivityTypeDescriptorProvider)), ActivityExecutor(GetType(CompositeActivityExecutor([Of] CompositeActivity))), ContentProperty("Activities"), DesignerSerializer(GetType(CompositeActivityMarkupSerializer), GetType(WorkflowMarkupSerializer)), ActivityCodeGenerator(GetType(CompositeActivityCodeGenerator)), ActivityValidator(GetType(CompositeActivityValidator))> _
    Public Class CompositeActivity
        Inherits Activity
        Implements ISupportAlternateFlow
        ' Methods
        Public Sub New()
            Me.activities = New ActivityCollection(Me)
            AddHandler Me.activities.ListChanging, New EventHandler([Of] ActivityCollectionChangeEventArgs)(AddressOf Me.OnListChangingEventHandler)
            AddHandler Me.activities.ListChanged, New EventHandler([Of] ActivityCollectionChangeEventArgs)(AddressOf Me.OnListChangedEventHandler)
            MyBase.SetValue(CompositeActivity.CanModifyActivitiesProperty, False)
        End Sub

        Public Sub New(ByVal children As IEnumerable([Of] Activity))
            Me.New()
            If (children Is Nothing) Then
                Throw New ArgumentNullException("children")
            End If
            Dim activity As Activity
            For Each activity In children
                Me.activities.Add(activity)
            Next
        End Sub

        Public Sub New(ByVal name As String)
            MyBase.New(name)
            Me.activities = New ActivityCollection(Me)
            AddHandler Me.activities.ListChanging, New EventHandler([Of] ActivityCollectionChangeEventArgs)(AddressOf Me.OnListChangingEventHandler)
            AddHandler Me.activities.ListChanged, New EventHandler([Of] ActivityCollectionChangeEventArgs)(AddressOf Me.OnListChangedEventHandler)
            MyBase.SetValue(CompositeActivity.CanModifyActivitiesProperty, False)
        End Sub

        Protected Sub ApplyWorkflowChanges(ByVal workflowChanges As WorkflowChanges)
            If (workflowChanges Is Nothing) Then
                Throw New ArgumentNullException("workflowChanges")
            End If
            If (Not MyBase.Parent Is Nothing) Then
                Throw New InvalidOperationException(SR.GetString("Error_InvalidActivityForWorkflowChanges"))
            End If
            If (MyBase.RootActivity Is Nothing) Then
                Throw New InvalidOperationException(SR.GetString("Error_MissingRootActivity"))
            End If
            If (MyBase.WorkflowCoreRuntime Is Nothing) Then
                Throw New InvalidOperationException(SR.GetString("Error_NoRuntimeAvailable"))
            End If
            workflowChanges.ApplyTo(Me)
        End Sub

        Private Shared Function CannotModifyChildren(ByVal compositeActivity As CompositeActivity, ByVal parent As Boolean) As Boolean
            If (compositeActivity Is Nothing) Then
                Throw New ArgumentNullException("compositeActivity")
            End If
            If (parent AndAlso (compositeActivity.Parent Is Nothing)) Then
                Return False
            End If
            Return (CBool(compositeActivity.GetValue(Activity.CustomActivityProperty)) OrElse ((Not compositeActivity.Parent Is Nothing) AndAlso CompositeActivity.CannotModifyChildren(compositeActivity.Parent, parent)))
        End Function

        Friend Overrides Function CollectNestedActivities() As IList([Of] Activity)
            Dim list As New List([Of] Activity)
            Dim queue As New Queue([Of] Activity)(Me.activities)
            Do While (queue.Count > 0)
                Dim item As Activity = queue.Dequeue
                list.Add(item)
                If TypeOf item Is CompositeActivity Then
                    Dim activity2 As Activity
                    For Each activity2 In DirectCast(item, CompositeActivity).activities
                        queue.Enqueue(activity2)
                    Next
                End If
            Loop
            Return list
        End Function

        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                Dim activity As Activity
                For Each activity In Me.Activities
                    activity.Dispose
                Next
            End If
            MyBase.Dispose(disposing)
        End Sub

        Friend Overrides Sub FixUpMetaProperties(ByVal originalObject As DependencyObject)
            If (originalObject Is Nothing) Then
                Throw New ArgumentNullException
            End If
            If Not TypeOf originalObject Is CompositeActivity Then
                Throw New ArgumentException
            End If
            MyBase.FixUpMetaProperties(originalObject)
            If (Not Me.activities Is Nothing) Then
                Dim activity As CompositeActivity = [TryCast](originalObject,CompositeActivity)
                If (Not activity Is Nothing) Then
                    Dim num As Integer = 0
                    Dim activity2 As Activity
                    For Each activity2 In Me.activities
                        activity2.FixUpMetaProperties(activity.activities.Item(num++))
                    Next
                End If
            End If
        End Sub

        Friend Overrides Sub FixUpParentChildRelationship(ByVal definitionActivity As Activity, ByVal parentActivity As Activity, ByVal deserializedActivities As Hashtable)
            Dim activity As CompositeActivity = [TryCast](definitionActivity,CompositeActivity)
            If (activity Is Nothing) Then
                Throw New ArgumentException("definitionActivity")
            End If
            MyBase.FixUpParentChildRelationship(definitionActivity, parentActivity, deserializedActivities)
            Me.activities = New ActivityCollection(Me)
            AddHandler Me.activities.ListChanging, New EventHandler([Of] ActivityCollectionChangeEventArgs)(AddressOf Me.OnListChangingEventHandler)
            AddHandler Me.activities.ListChanged, New EventHandler([Of] ActivityCollectionChangeEventArgs)(AddressOf Me.OnListChangedEventHandler)
            Dim dottedPath As String = MyBase.DottedPath
            Dim num As Integer = 0
            Dim activity2 As Activity
            For Each activity2 In activity.activities
                Dim activity3 As Activity = DirectCast(deserializedActivities.Item(If((dottedPath.Length = 0), num.ToString(CultureInfo.InvariantCulture), (dottedPath & "." & num.ToString(CultureInfo.InvariantCulture)))), Activity)
                Me.activities.InnerAdd(activity3)
                activity3.FixUpParentChildRelationship(activity2, Me, deserializedActivities)
                num += 1
            Next
        End Sub

        Protected Function GetDynamicActivities(ByVal activity As Activity) As Activity()
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            If (Not activity.parent Is Me) Then
                Throw New ArgumentException(SR.GetString("GetDynamicActivities_InvalidActivity"), "activity")
            End If
            Dim contextActivity As Activity = MyBase.ContextActivity
            Dim list As New List([Of] Activity)
            If (Not contextActivity Is Nothing) Then
                Dim list2 As IList([Of] Activity) = DirectCast(contextActivity.GetValue(Activity.ActiveExecutionContextsProperty), IList([Of] Activity))
                If (Not list2 Is Nothing) Then
                    Dim activity3 As Activity
                    For Each activity3 In list2
                        If activity3.MetaEquals(activity) Then
                            list.Add(activity3)
                        End If
                    Next
                End If
            End If
            Return list.ToArray
        End Function

        Protected Friend Overrides Function HandleFault(ByVal executionContext As ActivityExecutionContext, ByVal exception As Exception) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            If (exception Is Nothing) Then
                Throw New ArgumentNullException("exception")
            End If
            Dim status As ActivityExecutionStatus = Me.Cancel(executionContext)
            If (status = ActivityExecutionStatus.Canceling) Then
                Return ActivityExecutionStatus.Faulting
            End If
            Return status
        End Function

        Protected Friend Overrides Sub Initialize(ByVal provider As IServiceProvider)
            If (provider Is Nothing) Then
                Throw New ArgumentNullException("provider")
            End If
            If Not TypeOf provider Is ActivityExecutionContext Then
                Throw New ArgumentException(SR.GetString("Error_InvalidServiceProvider", New Object() { "provider" }))
            End If
            Dim activity As Activity
            For Each activity In Helpers.GetAllEnabledActivities(Me)
                [TryCast](provider,ActivityExecutionContext).InitializeActivity(activity)
            Next
        End Sub

        Private Shared Function IsDynamicMode(ByVal compositeActivity As CompositeActivity) As Boolean
            If (compositeActivity Is Nothing) Then
                Throw New ArgumentNullException("compositeActivity")
            End If
            Do While (Not compositeActivity.Parent Is Nothing)
                If compositeActivity.DynamicUpdateMode Then
                    Return True
                End If
                compositeActivity = compositeActivity.Parent
            Loop
            Return compositeActivity.DynamicUpdateMode
        End Function

        Protected Friend Overridable Sub OnActivityChangeAdd(ByVal executionContext As ActivityExecutionContext, ByVal addedActivity As Activity)
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            If (addedActivity Is Nothing) Then
                Throw New ArgumentNullException("addedActivity")
            End If
        End Sub

        Protected Friend Overridable Sub OnActivityChangeRemove(ByVal executionContext As ActivityExecutionContext, ByVal removedActivity As Activity)
        End Sub

        Protected Friend Overrides Sub OnActivityExecutionContextLoad(ByVal provider As IServiceProvider)
            If (provider Is Nothing) Then
                Throw New ArgumentNullException("provider")
            End If
            MyBase.OnActivityExecutionContextLoad(provider)
            Dim activity As Activity
            For Each activity In Helpers.GetAllEnabledActivities(Me)
                activity.OnActivityExecutionContextLoad(provider)
            Next
        End Sub

        Protected Friend Overrides Sub OnActivityExecutionContextUnload(ByVal provider As IServiceProvider)
            If (provider Is Nothing) Then
                Throw New ArgumentNullException("provider")
            End If
            MyBase.OnActivityExecutionContextUnload(provider)
            Dim activity As Activity
            For Each activity In Helpers.GetAllEnabledActivities(Me)
                activity.OnActivityExecutionContextUnload(provider)
            Next
        End Sub

        Friend Overrides Sub OnInitializeActivatingInstanceForRuntime(ByVal workflowCoreRuntime As IWorkflowCoreRuntime)
            MyBase.OnInitializeActivatingInstanceForRuntime(workflowCoreRuntime)
            Dim activity As Activity
            For Each activity In Me.activities
                If activity.Enabled Then
                    DirectCast(activity, IDependencyObjectAccessor).InitializeActivatingInstanceForRuntime(Nothing, workflowCoreRuntime)
                Else
                    MyBase.Readonly = True
                End If
            Next
        End Sub

        Friend Overrides Sub OnInitializeDefinitionForRuntime()
            If MyBase.DesignMode Then
                MyBase.OnInitializeDefinitionForRuntime
                Dim hashtable As Hashtable = DirectCast(MyBase.RootActivity.UserData.Item(UserDataKeys.LookupPaths), Hashtable)
                Dim str As String = CStr(hashtable.Item(MyBase.QualifiedName))
                Dim activity2 As Activity
                For Each activity2 In DirectCast(Me.activities, IEnumerable)
                    If activity2.Enabled Then
                        Dim str2 As String = str
                        If Not String.IsNullOrEmpty(str) Then
                            str2 = (str2 & ".")
                        End If
                        str2 = (str2 & Me.activities.IndexOf(activity2).ToString(CultureInfo.InvariantCulture))
                        hashtable.Add(activity2.QualifiedName, str2)
                        DirectCast(activity2, IDependencyObjectAccessor).InitializeDefinitionForRuntime(Nothing)
                        [Continue] For
                    End If
                    activity2.OnInitializeDefinitionForRuntime
                    activity2.Readonly = True
                Next
            End If
        End Sub

        Friend Overrides Sub OnInitializeInstanceForRuntime(ByVal workflowCoreRuntime As IWorkflowCoreRuntime)
            MyBase.OnInitializeInstanceForRuntime(workflowCoreRuntime)
            Dim activity As Activity
            For Each activity In Me.activities
                If activity.Enabled Then
                    DirectCast(activity, IDependencyObjectAccessor).InitializeInstanceForRuntime(workflowCoreRuntime)
                End If
            Next
        End Sub

        Protected Overridable Sub OnListChanged(ByVal e As ActivityCollectionChangeEventArgs)
            If (e Is Nothing) Then
                Throw New ArgumentNullException("e")
            End If
            If (((e.Action = ActivityCollectionChangeAction.Replace) OrElse (e.Action = ActivityCollectionChangeAction.Remove)) AndAlso (Not e.RemovedItems Is Nothing)) Then
                Dim activity As Activity
                For Each activity In e.RemovedItems
                    activity.SetParent(Nothing)
                Next
            End If
            If (((e.Action = ActivityCollectionChangeAction.Replace) OrElse (e.Action = ActivityCollectionChangeAction.Add)) AndAlso (Not e.AddedItems Is Nothing)) Then
                Dim activity2 As Activity
                For Each activity2 In e.AddedItems
                    activity2.SetParent(Me)
                Next
                Dim queue As New Queue([Of] Activity)(e.AddedItems)
                Do While (queue.Count > 0)
                    Dim activity3 As Activity = queue.Dequeue
                    If ((Not activity3 Is Nothing) AndAlso (((activity3.Name Is Nothing) OrElse (activity3.Name.Length = 0)) OrElse (activity3.Name = activity3.GetType.Name))) Then
                        Dim rootActivity As Activity = Helpers.GetRootActivity(activity3)
                        Dim str As String = [TryCast](rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty),String)
                        If ((rootActivity.Parent Is Nothing) OrElse Not String.IsNullOrEmpty(str)) Then
                            Dim list As New ArrayList
                            list.AddRange(Helpers.GetIdentifiersInCompositeActivity([TryCast](rootActivity,CompositeActivity)))
                            activity3.Name = DesignerHelpers.GenerateUniqueIdentifier(Me.Site, Helpers.GetBaseIdentifier(activity3), DirectCast(list.ToArray(GetType(String)), String()))
                        End If
                    End If
                    If TypeOf activity3 Is CompositeActivity Then
                        Dim activity5 As Activity
                        For Each activity5 In DirectCast(activity3, CompositeActivity).Activities
                            queue.Enqueue(activity5)
                        Next
                    End If
                Loop
            End If
            If (Not Me.Site Is Nothing) Then
                Dim service As IComponentChangeService = [TryCast](Me.Site.GetService(GetType(IComponentChangeService)),IComponentChangeService)
                If (Not service Is Nothing) Then
                    service.OnComponentChanged(Me, Nothing, e, Nothing)
                End If
            End If
        End Sub

        Private Sub OnListChangedEventHandler(ByVal sender As Object, ByVal e As ActivityCollectionChangeEventArgs)
            Me.OnListChanged(e)
        End Sub

        Protected Overridable Sub OnListChanging(ByVal e As ActivityCollectionChangeEventArgs)
            If (e Is Nothing) Then
                Throw New ArgumentNullException("e")
            End If
            If ((e.Action = ActivityCollectionChangeAction.Add) AndAlso (Not e.AddedItems Is Nothing)) Then
                Dim activity As Activity
                For Each activity In e.AddedItems
                    If (Not activity.Parent Is Nothing) Then
                        Throw New InvalidOperationException(SR.GetString("Error_ActivityHasParent", New Object() { activity.QualifiedName, activity.Parent.QualifiedName }))
                    End If
                    If (activity Is Me) Then
                        Throw New InvalidOperationException(SR.GetString("Error_Recursion", New Object() { activity.QualifiedName }))
                    End If
                Next
            End If
            If (Not Me.Site Is Nothing) Then
                Dim service As IComponentChangeService = [TryCast](Me.Site.GetService(GetType(IComponentChangeService)),IComponentChangeService)
                If (Not service Is Nothing) Then
                    service.OnComponentChanging(Me, Nothing)
                End If
            End If
        End Sub

        Private Sub OnListChangingEventHandler(ByVal sender As Object, ByVal e As ActivityCollectionChangeEventArgs)
            If (Not MyBase.DesignMode AndAlso Not MyBase.DynamicUpdateMode) Then
                Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
            End If
            If Not Me.CanModifyActivities Then
                If ((MyBase.DesignMode AndAlso (Not Activity.ActivityType Is Nothing)) AndAlso (MyBase.GetType Is Activity.ActivityType)) Then
                    Throw New InvalidOperationException(SR.GetString("Error_Missing_CanModifyProperties_True", New Object() { MyBase.GetType.FullName }))
                End If
                If (Not CompositeActivity.IsDynamicMode(Me) AndAlso CompositeActivity.CannotModifyChildren(Me, False)) Then
                    Throw New InvalidOperationException(SR.GetString("Error_CannotAddRemoveChildActivities"))
                End If
                If (CompositeActivity.IsDynamicMode(Me) AndAlso CompositeActivity.CannotModifyChildren(Me, True)) Then
                    Throw New InvalidOperationException(SR.GetString("Error_CannotAddRemoveChildActivities"))
                End If
            End If
            If ((e.Action = ActivityCollectionChangeAction.Add) AndAlso (Not e.AddedItems Is Nothing)) Then
                Dim activity As Activity = Me
                Do While (Not activity Is Nothing)
                    If e.AddedItems.Contains(activity) Then
                        Throw New InvalidOperationException(SR.GetString("Error_ActivityCircularReference"))
                    End If
                    activity = activity.Parent
                Loop
            End If
            Me.OnListChanging(e)
        End Sub

        Protected Friend Overridable Sub OnWorkflowChangesCompleted(ByVal rootContext As ActivityExecutionContext)
        End Sub

        Friend Overrides Function TraverseDottedPath(ByVal dottedPath As String) As Activity
            Dim str As String = dottedPath
            Dim str2 As String = String.Empty
            Dim index As Integer = dottedPath.IndexOf("."c)
            If (index <> -1) Then
                str = dottedPath.Substring(0, index)
                str2 = dottedPath.Substring((index + 1))
            End If
            Dim num2 As Integer = Convert.ToInt32(str, CultureInfo.InvariantCulture)
            If (num2 >= Me.activities.Count) Then
                Return Nothing
            End If
            Dim activity As Activity = Me.activities.Item(num2)
            If Not String.IsNullOrEmpty(str2) Then
                Return activity.TraverseDottedPath(str2)
            End If
            Return activity
        End Function

        Protected Friend Overrides Sub Uninitialize(ByVal provider As IServiceProvider)
            If (provider Is Nothing) Then
                Throw New ArgumentNullException("provider")
            End If
            Dim activity As Activity
            For Each activity In Helpers.GetAllEnabledActivities(Me)
                If (activity.ExecutionResult <> ActivityExecutionResult.Uninitialized) Then
                    activity.Uninitialize(provider)
                    activity.SetValue(Activity.ExecutionResultProperty, ActivityExecutionResult.Uninitialized)
                End If
            Next
            MyBase.Uninitialize(provider)
        End Sub


        ' Properties
        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property Activities As ActivityCollection
            Get
                Return Me.activities
            End Get
        End Property

        Protected Friend Property CanModifyActivities As Boolean
            Get
                Return CBool(MyBase.GetValue(CompositeActivity.CanModifyActivitiesProperty))
            End Get
            Set(ByVal value As Boolean)
                MyBase.SetValue(CompositeActivity.CanModifyActivitiesProperty, value)
                If (Me.Activities.Count > 0) Then
                    MyBase.SetValue(Activity.CustomActivityProperty, True)
                End If
            End Set
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public ReadOnly Property EnabledActivities As ReadOnlyCollection([Of] Activity)
            Get
                Dim list As New List([Of] Activity)
                Dim activity As Activity
                For Each activity In Me.activities
                    If (activity.Enabled AndAlso Not Helpers.IsFrameworkActivity(activity)) Then
                        list.Add(activity)
                    End If
                Next
                Return list.AsReadOnly
            End Get
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Private ReadOnly Property System.Workflow.ComponentModel.ISupportAlternateFlow.AlternateFlowActivities As IList([Of] Activity)
            Get
                Dim list As New List([Of] Activity)
                Dim activity As Activity
                For Each activity In Me.activities
                    If (activity.Enabled AndAlso Helpers.IsFrameworkActivity(activity)) Then
                        list.Add(activity)
                    End If
                Next
                Return list.AsReadOnly
            End Get
        End Property


        ' Fields
        <NonSerialized> _
        Private activities As ActivityCollection
        Private Shared CanModifyActivitiesProperty As DependencyProperty = DependencyProperty.Register("CanModifyActivities", GetType(Boolean), GetType(CompositeActivity), New PropertyMetadata(DependencyPropertyOptions.Metadata, New Attribute() { New DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }))
    End Class
End Namespace

